package org.cleverframe.core.qlscript.utils;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;

import org.cleverframe.common.spring.SpringBeanNames;
import org.cleverframe.common.spring.SpringContextHolder;
import org.cleverframe.core.qlscript.QLScriptBeanNames;
import org.cleverframe.core.qlscript.entity.QLScript;
import org.cleverframe.core.qlscript.service.IQLScriptService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * 获取脚本工具类<br>
 * 
 * @author LiZW
 * @version 2015年6月24日 下午12:24:52
 */
public class QLScriptUtils
{
    /** 日志对象 */
    private final static Logger logger = LoggerFactory.getLogger(QLScriptUtils.class);

    /** FreeMarker容器，不能直接使用此属性 */
    private static Configuration configuration;

    /** 数据库脚本Service，不能直接使用此属性 */
    private static IQLScriptService qLScriptService;

    /** 得到 FreeMarker容器*/
    public static Configuration getConfiguration()
    {
        if (configuration == null)
        {
            // 初始化FreeMarker
            FreeMarkerConfigurer freeMarkerConfigurer = SpringContextHolder.getBean(SpringBeanNames.FREEMARKER_CONFIG);
            configuration = freeMarkerConfigurer.getConfiguration();
            QLScriptTemplateLoader qLScriptTemplateLoader = SpringContextHolder.getBean(QLScriptBeanNames.QLScriptTemplateLoader);
            qLScriptTemplateLoader.setLocale(configuration.getLocale().toString());
            // 注册自定义模版加载器--从数据库加载"数据库脚本"模版
            configuration.setTemplateLoader(qLScriptTemplateLoader);
        }
        return configuration;
    }

    /**
     * 获取数据库脚本Service<br>
     * */
    public static IQLScriptService getQLScriptService()
    {
        if (qLScriptService == null)
        {
            qLScriptService = SpringContextHolder.getBean(QLScriptBeanNames.MemoryQLScriptService);
        }
        return qLScriptService;
    }

    /**
     * 获取QLScript对象<br>
     * @param name 脚本名称，使用包名称+类名+方法名
     * @return 若脚本不存在返回null
     */
    public static QLScript getScript(String name)
    {
        QLScript qLScript = null;
        try
        {
            qLScript = getQLScriptService().getQLScriptByName(name);
        }
        catch (Exception e)
        {
            logger.error("获取脚本异常", e);
        }
        if (qLScript == null)
        {
            return null;
        }
        return qLScript;
    }

    /**
     * 获取SQL脚本<br>
     * @param name 脚本名称，使用包名称+类名+方法名
     * @return 若脚本不存在，抛出异常
     */
    public static String getSQLScript(String name)
    {
        QLScript qLScript = null;
        try
        {
            qLScript = getQLScriptService().getQLScriptByName(name);
        }
        catch (Exception e)
        {
            logger.error("获取脚本异常", e);
        }
        if (qLScript == null || !QLScript.TYPE_SQL.equals(qLScript.getScriptType()))
        {
            throw new RuntimeException("脚本[" + name + "]不存在");
        }
        return qLScript.getScript();
    }

    /**
     * 获取HQL脚本<br>
     * @param name 脚本名称，使用包名称+类名+方法名
     * @return 若脚本不存在，抛出异常
     */
    public static String getHQLScript(String name)
    {
        QLScript qLScript = null;
        try
        {
            qLScript = getQLScriptService().getQLScriptByName(name);
        }
        catch (Exception e)
        {
            logger.error("获取脚本异常", e);
        }
        if (qLScript == null || !QLScript.TYPE_HQL.equals(qLScript.getScriptType()))
        {
            throw new RuntimeException("脚本[" + name + "]不存在");
        }
        return qLScript.getScript();
    }

    /**
     * 根据脚本名称和模板数据组装SQL脚本
     * @param name 脚本名称，使用包名称+类名+方法名
     * @param map 设置用于组装SQL的数据(模板数据)
     * @return 返回根据数据组装好的SQL脚本
     */
    public static String getSQLScript(String name, Map<String, Object> dataModel)
    {
        StringWriter sql = new StringWriter();
        try
        {
            Template template = getConfiguration().getTemplate(name);
            template.process(dataModel, sql);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (TemplateException e)
        {
            e.printStackTrace();
        }
        return sql.toString();
    }

    /**
     * 根据脚本名称和模板数据组装HQL脚本
     * @param name 脚本名称，使用包名称+类名+方法名
     * @param map 设置用于组装HQL的数据(模板数据)
     * @return 返回根据数据组装好的HQL脚本
     */
    public static String getHQLScript(String name, Map<String, Object> dataModel)
    {
        return getSQLScript(name, dataModel);
    }

    /**
     * 获取数据库脚本，并刷新QLScript缓存和FreeMarker缓存
     * @param name 脚本名称，使用包名称+类名+方法名
     * @return 刷新缓存成功返回新的QLScript，否则返回null
     */
    public static QLScript refreshQLScript(String name)
    {
        QLScript qLScript = null;
        try
        {
            qLScript = getQLScriptService().refreshQLScript(name);
        }
        catch (Exception e)
        {
            logger.error("刷新缓存脚本异常", e);
        }
        if (qLScript != null)
        {
            try
            {
                getConfiguration().removeTemplateFromCache(name);
            }
            catch (IOException e)
            {
                logger.error("removeTemplateFromCache异常", e);
            }
        }
        return qLScript;
    }

    /**
     * 根据脚本名称，移除FreeMarker缓存
     * @param name 脚本名称，使用包名称+类名+方法名
     */
    public static void removeTemplateCache(String name)
    {
        try
        {
            getConfiguration().removeTemplateFromCache(name);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}
